<?php
namespace Framework\Library;

use libphonenumber\NumberParseException;
use libphonenumber\PhoneNumberFormat;
use libphonenumber\PhoneNumberType;
use libphonenumber\PhoneNumberUtil;

class PhoneNumber
{
    private static $phoneNumberParseResults = [];
    private static $phoneNumberValidResults = [];

    public static function getFormattedMobileNumber($phoneNumber, $country = 'CN')
    {
        if (!self::isValidMobileNumber($phoneNumber, $country)) {
            return false;
        }
        if (($phoneNumberProto = self::getPhoneNumberParseResult($phoneNumber, $country)) === false) {
            return false;
        }

        return PhoneNumberUtil::getInstance()->format($phoneNumberProto, PhoneNumberFormat::E164);
    }

    public static function getNationalNumber($phoneNumber, $country = 'CN')
    {
        if (!self::isValidMobileNumber($phoneNumber, $country)) {
            return false;
        }
        if (($phoneNumberProto = self::getPhoneNumberParseResult($phoneNumber, $country)) === false) {
            return false;
        }

        return $phoneNumberProto->getNationalNumber();
    }

    public static function getCountryCode($phoneNumber, $country = 'CN')
    {
        if (!self::isValidMobileNumber($phoneNumber, $country)) {
            return false;
        }
        if (($phoneNumberProto = self::getPhoneNumberParseResult($phoneNumber, $country)) === false) {
            return false;
        }

        return $phoneNumberProto->getCountryCode();
    }

    public static function isForeignMobileNumber($formattedPhoneNumber)
    {
        return self::getCountryCode($formattedPhoneNumber) != '86';
    }

    public static function isValidMobileNumber($phoneNumber, $country = 'CN')
    {
        $key = $phoneNumber . ':' . $country;
        if (isset(self::$phoneNumberValidResults[$key])) {
            return self::$phoneNumberValidResults[$key];
        }

        if (($phoneNumberProto = self::getPhoneNumberParseResult($phoneNumber, $country)) === false) {
            return false;
        }
        $phoneUtil = PhoneNumberUtil::getInstance();
        $phoneNumberType = $phoneUtil->getNumberType($phoneNumberProto);
        $isValid = $phoneUtil->isValidNumber($phoneNumberProto) && ($phoneNumberType === PhoneNumberType::MOBILE || $phoneNumberType === PhoneNumberType::FIXED_LINE_OR_MOBILE);
        self::$phoneNumberValidResults[$key] = $isValid;

        return $isValid;
    }

    public static function getPhoneNumberParseResult($phoneNumber, $country = 'CN')
    {
        $key = $phoneNumber . ':' . $country;
        if (isset(self::$phoneNumberParseResults[$key])) {
            return self::$phoneNumberParseResults[$key];
        }

        try {
            $phoneUtil = PhoneNumberUtil::getInstance();
            $phoneNumberParseResult = $phoneUtil->parse($phoneNumber, $country);
            self::$phoneNumberParseResults[$key] = $phoneNumberParseResult;

            return $phoneNumberParseResult;
        } catch (NumberParseException $e) {
            return false;
        }
    }
}
